﻿using Microsoft.AspNetCore.Mvc;
using RuoVea.ExSugar.Dto;
using RuoVea.ExSugar;
using Org.BouncyCastle.Asn1.X509;
using System.Collections.Generic;

namespace RuoVea.Notes.Server.Service;

[ApiExplorerSettings(GroupName = "Note")]
public partial class NoteService : IApplicationService
{
    private readonly SugarRepository<NtNote> _noteRepository;
    private readonly ICurrentUser _currentUser;

    public NoteService(SugarRepository<NtNote> noteRepository, ICurrentUser currentUser)
    {
        _noteRepository = noteRepository;
        _currentUser = currentUser;
    }

    /// <summary>
    /// 查询所有/分页
    /// </summary>
    /// <param name="data"></param>
    /// <returns></returns>
    public async Task<RestfulResult<PageResult<NtNote>>> GetPagesAsync(NotePageParam? data)
    {
        var restful = new RestfulResult<PageResult<NtNote>>() { Code = CodeStatus.OK };
        data ??= new NotePageParam { PageNo = 1, PageSize = 10 };
        var query = await _noteRepository.AsQueryable()
            .Where(u => u.Creator == _currentUser.UserId)
            .Where(u => u.CategoryId == data.CategoryId)
            .Select((u) => new NtNote
            {
                Id = u.Id,
                CategoryId = u.CategoryId,
                Tags = SqlFunc.Subqueryable<NtTag>().InnerJoin<NtNoteTag>((t, nt) => nt.TagId == t.Id).Where((t, nt) => nt.NoteId == u.Id).ToList((t, nt)=>t),
                TagIds = SqlFunc.Subqueryable<NtNoteTag>().Where((t) => t.NoteId == u.Id).ToList((t) => t.TagId),
                Content = u.Content,
                CreateTime = u.CreateTime,
                Title = u.Title,
                Creator = u.Creator
            })
            .ToPageAsync(data.PageNo, data.PageSize);

        restful.Data = query;
        return restful;
    }

    /// <summary>
    /// 增加
    /// </summary>
    /// <param name="data"></param>
    /// <returns></returns>
    [UnitOfWork]
    public async Task<RestfulResult> AddAsync([FromBody] NtNote data)
    {
        RestfulResult restful = new() { Code = CodeStatus.BadRequest };
        var isExist = await _noteRepository.IsAnyAsync(u => u.Title == data.Title && u.Creator == _currentUser.UserId);
        if (isExist)
        {
            restful.Message = "标题重复";
            return restful;
        }
        data.Creator = _currentUser.UserId;
        var contextTran = _noteRepository.Context;
        try
        {
            await contextTran.Ado.BeginTranAsync();
            bool result = await contextTran.Insertable(data).IgnoreColumns(true).EnableDiffLogEventIF(false, null).ExecuteCommandAsync()>0;
            bool resultNtNoteTag = true;
            if (data.TagIds.Count > 0)
            {
                List<NtNoteTag> noteTags = data.TagIds.Select(x => new NtNoteTag { NoteId = data.Id, TagId = x }).ToList();
                resultNtNoteTag = await contextTran.Insertable(noteTags).IgnoreColumns(true).EnableDiffLogEventIF(false, null).ExecuteCommandAsync() > 0;
            }
            if (result&& resultNtNoteTag)
            {
                await contextTran.Ado.CommitTranAsync();
                restful.Data = result;
                restful.Code = CodeStatus.OK;
                return restful;
            }
            else
            {
                await contextTran.Ado.RollbackTranAsync();
                restful.Message = "添加失败";
                return restful;
            }
        }
        catch (Exception ex) 
        {
            await contextTran.Ado.RollbackTranAsync();
            restful.Message = ex.Message;
            return restful;
        }
    }

    /// <summary>
    /// 更新
    /// </summary>
    /// <param name="data"></param>
    /// <returns></returns>
    public async Task<RestfulResult> UpdateAsync([FromBody] NtNote data)
    {
        RestfulResult restful = new() { Code = CodeStatus.BadRequest };
        var isExist = await _noteRepository.IsAnyAsync(u => u.Id == data.Id && u.Creator == _currentUser.UserId);
        if (!isExist)
        {
            restful.Message = "记录不存在";
            return restful;
        }

        data.Creator = _currentUser.UserId;
        var contextTran = _noteRepository.Context;
        try
        {
            await contextTran.Ado.BeginTranAsync();
            bool result = await contextTran.Updateable(data).IgnoreColumns(true).EnableDiffLogEventIF(true, "笔记修改").ExecuteCommandAsync() > 0;

            List <NtNoteTag> noteTags = data.TagIds.Select(x => new NtNoteTag { NoteId = data.Id, TagId = x }).ToList();
            bool deleData= await contextTran.Deleteable<NtNoteTag>().WhereColumns(noteTags, it => new { it.NoteId }).ExecuteCommandAsync()>0;
            bool resultNtNoteTag = true;
            if (data.TagIds.Count > 0)
            {
                resultNtNoteTag = await contextTran.Insertable(noteTags).IgnoreColumns(true).EnableDiffLogEventIF(false, null).ExecuteCommandAsync() > 0;
            }
            if (result && resultNtNoteTag)
            {
                await contextTran.Ado.CommitTranAsync();
                restful.Data = result;
                restful.Code = CodeStatus.OK;
                return restful;
            }
            else
            {
                await contextTran.Ado.RollbackTranAsync();
                restful.Message = "修改失败";
                return restful;
            }
        }
        catch (Exception ex)
        {
            await contextTran.Ado.RollbackTranAsync();
            restful.Message = ex.Message;
            return restful;
        }
    }

    /// <summary>
    /// 删除
    /// </summary>
    /// <param name="data"></param>
    /// <returns></returns>
    public async Task<RestfulResult> DeleteAsync([FromBody] EntityBaseIdDto data)
    {
        RestfulResult restful = new() { Code = CodeStatus.BadRequest };

        if (data.Id == 0)
        {
            restful.Message = "删除失败";
            return restful;
        }
        bool isDelete = await _noteRepository.DeleteByIdAsync(data.Id);
        if (isDelete)
        {
            restful.Data = isDelete;
            restful.Message = "删除成功";
            restful.Code = CodeStatus.OK;
            return restful;
        }
        else
        {
            restful.Data = isDelete;
            restful.Message = "删除失败";
            return restful;
        }
    }
}